/**
 * 
 */
package com.ffcs.crmd.tsp.server.netty.processor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ffcs.crmd.tsp.api.dto.client.TspJobDetailRunning;
import com.ffcs.crmd.tsp.api.dto.netty.RemotingCommand;
import com.ffcs.crmd.tsp.api.dto.page.PageInfo;
import com.ffcs.crmd.tsp.api.dto.page.RetVo;
import com.ffcs.crmd.tsp.api.netty.INettyProcessor;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.common.netty.ResponseCode;
import com.ffcs.crmd.tsp.core.util.RemotingUtil;
import com.ffcs.crmd.tsp.core.util.XmlUtil;
import com.ffcs.crmd.tsp.server.application.ApplicationManagerHolder;
import com.ffcs.crmd.tsp.server.core.DataBaseHandler;
import com.ffcs.crmd.tsp.server.core.RemotingHandler;
import com.ffcs.crmd.tsp.server.jdbc.entity.Job;
import com.ffcs.crmd.tsp.server.jdbc.entity.JobDetail;
import com.ffcs.crmd.tsp.server.jdbc.entity.JobGroup;
import com.ffcs.crmd.tsp.server.job.info.JobDetailShell;
import com.ffcs.crmd.tsp.server.manager.JobProcessManager;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;

/**
 * 功能说明:
 *
 * @author ZHONGFUHUA
 * 
 * @since 
 *
 */
public class QueryJobDetailRunningProcessor implements INettyProcessor {
    /**
     * 日志
     */
    private final static Logger LOG               = LoggerFactory.getLogger(LoggerName.RemotingLoggerName);
    
    /**
     * 任务数据库服务
     */
    private DataBaseHandler     dataBaseHandler;
    
    /**
     * 任务端管理器
     */
    private JobProcessManager   jobProcessManager = ApplicationManagerHolder.getBean("jobProcessManager", JobProcessManager.class);
    
    /**
     * 功能说明:
     * 
     * @param remotingController
     */
    public QueryJobDetailRunningProcessor(RemotingHandler remotingController, DataBaseHandler dataBaseHandler) {
        this.dataBaseHandler = dataBaseHandler;
    }
    
    @Override
    public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) {
        RemotingCommand response = RemotingCommand.createResponseCommand(ResponseCode.SUCCESS);
        String requestXml = new String(request.getBody());
        try {
            LOG.info("SERVER-NETTY: one request to query job detail running is received that body=[{}]", requestXml);
            TspJobDetailRunning tspJobDetailRunningVO = (TspJobDetailRunning) XmlUtil.fromXml(requestXml, TspJobDetailRunning.class);
            List<Job> jobList = new ArrayList<Job>();
            if (StringUtils.isNoneBlank(tspJobDetailRunningVO.getJobGroupName())) {
                JobGroup jobGroupParam = new JobGroup();
                jobGroupParam.setName(tspJobDetailRunningVO.getJobGroupName());
                jobGroupParam.setClusterName(tspJobDetailRunningVO.getClusterName());
                JobGroup jobGroup = dataBaseHandler.getServiceSupport().getJobGroup(jobGroupParam);
                
                if(jobGroup != null){
                    Job jobParam = new Job();
                    jobParam.setJobGroupId(jobGroup.getId());
                    jobList.addAll(dataBaseHandler.getServiceSupport().queryJob(jobParam));
                }
            } else if (StringUtils.isNoneBlank(tspJobDetailRunningVO.getJobName())) {
                Job jobParam = new Job();
                jobParam.setName(tspJobDetailRunningVO.getJobName());
                jobParam.setClusterName(tspJobDetailRunningVO.getClusterName());
                jobList.add(dataBaseHandler.getServiceSupport().getJob(jobParam));
            } else if (StringUtils.isNoneBlank(tspJobDetailRunningVO.getJobDetailName())) {
                JobDetail jobDetailParam = new JobDetail();
                jobDetailParam.setName(tspJobDetailRunningVO.getJobDetailName());
                jobDetailParam.setClusterName(tspJobDetailRunningVO.getClusterName());
                JobDetail jobDetail = dataBaseHandler.getServiceSupport().getJobDetail(jobDetailParam);
                
                Job jobParam = new Job();
                jobParam.setId(jobDetail.getJobId());
                jobList.add(dataBaseHandler.getServiceSupport().getJob(jobParam));
            }else{
                Job jobParam = new Job();
                jobList.addAll(dataBaseHandler.getServiceSupport().queryJob(jobParam));
            }
            
            List<TspJobDetailRunning> tspJobDetailRunningVOList = new ArrayList<TspJobDetailRunning>();
            for (Job job : jobList) {
                Map<Channel, LinkedList<JobDetailShell>> jobDetailRunningMap = jobProcessManager.getJobDetailRunningChannel(job.getName());
                if (MapUtils.isEmpty(jobDetailRunningMap)) {
                    continue;
                }
                Iterator<Entry<Channel, LinkedList<JobDetailShell>>> jobDetailRunningMapIt = jobDetailRunningMap.entrySet().iterator();
                while (jobDetailRunningMapIt.hasNext()) {
                    Entry<Channel, LinkedList<JobDetailShell>> jobDetailRunningMapEntry = jobDetailRunningMapIt.next();
                    Channel channel = jobDetailRunningMapEntry.getKey();
                    
                    LinkedList<JobDetailShell> jobDetailShellList = jobDetailRunningMapEntry.getValue();
                    for (JobDetailShell jobDetailShell : jobDetailShellList) {
                        if (StringUtils.isNoneBlank(tspJobDetailRunningVO.getJobDetailName())
                            && !tspJobDetailRunningVO.getJobDetailName().equals(jobDetailShell.getJobDetailName())) {
                            continue;
                        }
                        
                        if (tspJobDetailRunningVO.getStatus() != null && tspJobDetailRunningVO.getStatus() != jobDetailShell.getStatus()) {
                            continue;
                        }
                        
                        if (StringUtils.isNoneBlank(tspJobDetailRunningVO.getAddr())
                            && !RemotingUtil.parseChannelRemote(channel).contains(tspJobDetailRunningVO.getAddr())) {
                            continue;
                        }
                        
                        if (StringUtils.isNoneBlank(tspJobDetailRunningVO.getId())
                            && !jobDetailShell.getId().equals(tspJobDetailRunningVO.getId())) {
                            continue;
                        }
                        
                        TspJobDetailRunning tspJobDetailRunning = new TspJobDetailRunning();
                        tspJobDetailRunning.setAddr(RemotingUtil.parseChannelRemote(channel));
                        tspJobDetailRunning.setId(jobDetailShell.getId());
                        tspJobDetailRunning.setJobDetailName(jobDetailShell.getContext().getTspJobInstance().getName());
                        tspJobDetailRunning.setJobName(jobDetailShell.getContext().getTspJobInstance().getJobName());
                        tspJobDetailRunning.setDescription(jobDetailShell.getContext().getTspJobInstance().getDescription());
                        tspJobDetailRunning.setStatus(jobDetailShell.getStatus());
                        tspJobDetailRunning.setClusterName(jobDetailShell.getClusterName());
                        tspJobDetailRunning.setInstanceId(jobDetailShell.getInstanceId());
                        tspJobDetailRunning.setFireTime(jobDetailShell.getFireTime());
                        tspJobDetailRunning.setSendTime(jobDetailShell.getSendTime());
                        tspJobDetailRunning.setReciveTime(jobDetailShell.getReciveTime());
                        tspJobDetailRunning.setRefireCount(jobDetailShell.getContext().getRefireCount());
                        tspJobDetailRunningVOList.add(tspJobDetailRunning);
                    }
                }
            }
            
            Collections.sort(tspJobDetailRunningVOList, new Comparator<TspJobDetailRunning>() {
                @Override
                public int compare(TspJobDetailRunning o1, TspJobDetailRunning o2) {
                    return o1.getId().compareTo(o2.getId());
                }
            });
            
            RetVo<TspJobDetailRunning> retVO = new RetVo<TspJobDetailRunning>();
            if (tspJobDetailRunningVO.getPageNumber() != null && tspJobDetailRunningVO.getPageSize()!= null 
                && tspJobDetailRunningVO.getPageNumber() > 0 && tspJobDetailRunningVO.getPageSize() > 0) {
                int pageNumber = tspJobDetailRunningVO.getPageNumber();
                int pageSize = tspJobDetailRunningVO.getPageSize();
                int totalCounts = tspJobDetailRunningVOList.size();
                int first = PageInfo.getPageBeginSize(pageSize, pageNumber);
                int end = PageInfo.getPageEndSize(first, pageSize, totalCounts);
                
                List<TspJobDetailRunning> ntspJobDetailRunningVOList = new ArrayList<TspJobDetailRunning>();
                ntspJobDetailRunningVOList.addAll(tspJobDetailRunningVOList.subList(first, end));
                
                PageInfo<TspJobDetailRunning> pageInfo = new PageInfo<TspJobDetailRunning>(ntspJobDetailRunningVOList);
                pageInfo.calcAndJudge(pageSize, pageNumber, totalCounts, ntspJobDetailRunningVOList);
                retVO.setPageInfo(pageInfo);
            } else {
                retVO.setDataList(tspJobDetailRunningVOList);
            }
            
            response.setBody(XmlUtil.toXml(retVO).getBytes());
        } catch (Exception e) {
            LOG.error("SERVER-NETTY: query job detail running[{}] exception:", requestXml, e);
            String responseBody = String.format("query job detail running exception:%s", e.getMessage());
            response.setCode(ResponseCode.FAIL);
            response.setBody(responseBody.getBytes());
        }
        return response;
    }
}
